﻿using System;
using System.IO;
using Logging;
using Microsoft.Cci.MutableCodeModel;
using PartialExpressionCompleter.Experiment;
using PartialExpressionCompleter.Util;
using System.Reflection;

namespace PartialExpressionCompleter
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                //Examples.Example.Main(args);
                string file = args[0];
                Microsoft.Cci.MutableCodeModel.Assembly unit;
                Exception loadingException = null;
                try
                {
                    unit = CCIUtil.LoadUnitFrom(file, true);
                }
                catch (Exception e)
                {
                    loadingException = e;
                    unit = null;
                }
                Experiment.Experiment experiment;
                if (args.Length > 1)
                {
                    if (args[1].Equals("--assignment"))
                    {
                        experiment = new AssignmentQueryExperiment(unit);
                    }
                    else if (args[1].Equals("--mquery"))
                    {
                        experiment = new MethodQueryExperiment(unit);
                    }
                    else if (args[1].Equals("--argquery"))
                    {
                        experiment = new ArgumentQueryExperiment(unit);
                    }
                    else if (args[1].Equals("--comparison"))
                    {
                        experiment = new ComparisonExperiment(unit);
                    }
                    else if (args[1].Equals("--count"))
                    {
                        experiment = new CountExperiment(unit);
                    }
                    else if (args[1].Equals("--mcount"))
                    {
                        experiment = new MethodForTypeCounter(unit);
                    }
                    else if (args[1].Equals("--abstypes"))
                    {
                        experiment = new AbstractTypesOutputter(unit);
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    experiment = new AbstractTypesOutputter(unit);
                }
                if (args.Length > 2 && !(experiment is AbstractTypesOutputter))
                {
                    Query.ScoreSwitches.SetSwitches(args[2]);
                }
                var info = new Lazy<AssemblyName>(() => AssemblyName.GetAssemblyName(file));
                string logFile = (args.Length > 2 && experiment is AbstractTypesOutputter
                                  ? args[2] + @"\" : @"s:\log\")
                    + new FileInfo(file).Name
                    + (experiment is AbstractTypesOutputter
                        ? "-" + info.Value.Version
                            + "-" + info.Value.GetPublicKeyToken().ToHexString()
                        : "")
                    + (experiment.FileExtension == null ? "" : "." + experiment.FileExtension)
                    + (args.Length > 2 && !(experiment is AbstractTypesOutputter) ? "." + args[2] : "")
                    + "." + DateTime.Now.ToString("s").Replace(":", "")
                    + ".txt";
                Logger.SetOutputFile(File.Open(logFile, FileMode.Create));

                /*
                foreach (var arg in args)
                {
                    Logger.PrintLine("Arg: " + arg);
                }*/
                if (unit == null)
                {
                    Logger.PrintLine(loadingException.ToString());
                    Logger.PrintLine(loadingException.StackTrace);
                }
                else
                {
                    experiment.RunExperiment();
                }
            }
            catch (Exception e)
            {
                Logger.PrintLine("Total failure: " + e.StackTrace);
            }
            try
            {
                Logger.Close();
            }
            catch (Exception)
            {
                // Failed to close log... not much to do here.
            }
        }
    }
}
